﻿package frEngine.core.lenses
{
    import __AS3__.vec.*;
    import flash.events.*;
    import flash.geom.*;

    public class LensBase extends EventDispatcher
    {
        protected var _matrix:Matrix3D;
        protected var _near:Number = 20;
        protected var _far:Number = 3000;
        protected var _aspectRatio:Number = 1;
        protected var _matrixInvalid:Boolean = true;
        protected var _frustumCorners:Vector.<Number>;
        private var _unprojection:Matrix3D;
        private var _unprojectionInvalid:Boolean = true;
        public var onInvalidateMatrix:Function;

        public function LensBase()
        {
            this._frustumCorners = new Vector.<Number>(8 * 3, true);
            this._matrix = new Matrix3D();
            return;
        }// end function

        public function get frustumCorners() : Vector.<Number>
        {
            return this._frustumCorners;
        }// end function

        public function set frustumCorners(param1:Vector.<Number>) : void
        {
            this._frustumCorners = param1;
            return;
        }// end function

        public function get matrix() : Matrix3D
        {
            if (this._matrixInvalid)
            {
                this.updateMatrix();
                this._matrixInvalid = false;
            }
            return this._matrix;
        }// end function

        public function set matrix(param1:Matrix3D) : void
        {
            this._matrix = param1;
            this.invalidateMatrix();
            return;
        }// end function

        public function get near() : Number
        {
            return this._near;
        }// end function

        public function set near(param1:Number) : void
        {
            if (param1 == this._near)
            {
                return;
            }
            this._near = param1;
            this.invalidateMatrix();
            return;
        }// end function

        public function get far() : Number
        {
            return this._far;
        }// end function

        public function set far(param1:Number) : void
        {
            if (param1 == this._far)
            {
                return;
            }
            this._far = param1;
            this.invalidateMatrix();
            return;
        }// end function

        public function project(param1:Vector3D) : Vector3D
        {
            var _loc_2:* = this.matrix.transformVector(param1);
            _loc_2.x = _loc_2.x / _loc_2.w;
            _loc_2.y = (-_loc_2.y) / _loc_2.w;
            return _loc_2;
        }// end function

        public function get unprojectionMatrix() : Matrix3D
        {
            if (this._unprojectionInvalid)
            {
                this._unprojection = this._unprojection || new Matrix3D();
                this._unprojection.copyFrom(this.matrix);
                this._unprojection.invert();
                this._unprojectionInvalid = false;
            }
            return this._unprojection;
        }// end function

        public function unproject(param1:Number, param2:Number, param3:Number) : Vector3D
        {
            var _loc_4:* = new Vector3D(param1, -param2, param3, 1);
            _loc_4 = this.unprojectionMatrix.transformVector(_loc_4);
            var _loc_5:* = 1 / _loc_4.w;
            _loc_4.x = _loc_4.x * _loc_5;
            _loc_4.y = _loc_4.y * _loc_5;
            _loc_4.z = _loc_4.z * _loc_5;
            _loc_4.w = 1;
            return _loc_4;
        }// end function

        public function clone() : LensBase
        {
            throw new Error("请覆盖方法");
        }// end function

        public function get aspectRatio() : Number
        {
            return this._aspectRatio;
        }// end function

        public function set aspectRatio(param1:Number) : void
        {
            if (this._aspectRatio == param1)
            {
                return;
            }
            this._aspectRatio = param1;
            this.invalidateMatrix();
            return;
        }// end function

        protected function invalidateMatrix() : void
        {
            this._matrixInvalid = true;
            this._unprojectionInvalid = true;
            if (this.onInvalidateMatrix != null)
            {
                this.onInvalidateMatrix();
            }
            return;
        }// end function

        protected function updateMatrix() : void
        {
            throw new Error("请覆盖方法");
        }// end function

    }
}
